package br.usp.ime.ingpos.web.controllers;

import java.util.List;

import org.springframework.util.StringUtils;

import br.com.caelum.vraptor.Get;
import br.com.caelum.vraptor.Path;
import br.com.caelum.vraptor.Post;
import br.com.caelum.vraptor.Resource;
import br.com.caelum.vraptor.Result;
import br.com.caelum.vraptor.Validator;
import br.com.caelum.vraptor.validator.Validations;
import br.usp.ime.ingpos.modelo.CartaDeRecomendacao;
import br.usp.ime.ingpos.modelo.Inscricao;
import br.usp.ime.ingpos.modelo.ProcessoSeletivo;
import br.usp.ime.ingpos.modelo.TipoCategoriaCandidato;
import br.usp.ime.ingpos.modelo.TipoConheceCandidato;
import br.usp.ime.ingpos.modelo.TipoLingua;
import br.usp.ime.ingpos.modelo.TipoPais;
import br.usp.ime.ingpos.modelo.TipoPerfil;
import br.usp.ime.ingpos.modelo.TipoProcessoSeletivo;
import br.usp.ime.ingpos.services.CartaDeRecomendacaoService;
import br.usp.ime.ingpos.services.InscricaoService;
import br.usp.ime.ingpos.web.interceptors.IrrestrictAccess;
import br.usp.ime.ingpos.web.interceptors.RestrictAccessPerfil;
import br.usp.ime.ingpos.web.interceptors.Transactional;

@Resource
public class CartaRecomendacaoController
{
    private static final String CARTAS_DE_RECOMENDACAO = "cartasDeRecomendacao";

    private final UsuarioSessao usuarioSessao;
    private final Result result;
    private final CartaDeRecomendacaoService cartaDeRecomendacaoService;
    private final Validator validador;
    private final InscricaoService inscricaoService;
    private CartaDeRecomendacao cartaDeRecomendacao = null;

    public CartaRecomendacaoController(
        final Result result,
        final Validator validator,
        final UsuarioSessao usuarioSessao,
        final CartaDeRecomendacaoService cartaDeRecomendacaoService,
        final InscricaoService inscricaoService )
    {
        this.result = result;
        this.validador = validator;
        this.usuarioSessao = usuarioSessao;
        this.cartaDeRecomendacaoService = cartaDeRecomendacaoService;
        this.inscricaoService = inscricaoService;
    }

    @Get
    @Path( "/cartaRecomendacao/solicitarRecomendacao" )
    @RestrictAccessPerfil( values = {
        TipoPerfil.COORDENADOR, TipoPerfil.PROFESSOR, TipoPerfil.SECRETARIA
    } )
    public void solicitarRecomendacao()
    {
        final List<CartaDeRecomendacao> cartasDeRecomendacao = cartaDeRecomendacaoService.procurarPorUsuario( usuarioSessao.getUsuario() );
        result.include( CARTAS_DE_RECOMENDACAO, cartasDeRecomendacao );
        result.include( "tipoLingua", TipoLingua.getTipoLingua() );
    }

    @Post
    @Path( "/cartaRecomendacao/solicitarRecomendacao" )
    @Transactional
    @RestrictAccessPerfil( values = {
        TipoPerfil.COORDENADOR, TipoPerfil.PROFESSOR, TipoPerfil.SECRETARIA
    } )
    public void solicitarRecomendacao(
        final CartaDeRecomendacao cartaDeRecomendacao )
    {
        validador.checking( new Validations() {
            {
                that( StringUtils.hasText( cartaDeRecomendacao.getNome() ),
                    "cadastro_recomendacao_nome", "erro_carta_recomendacao_nome_vazio" );

                that( StringUtils.hasText( cartaDeRecomendacao.getInstituicao() ),
                    "cadastro_recomendacao_instituicao",
                    "erro_carta_recomendacao_instituicao_vazio" );

                that( StringUtils.hasText( cartaDeRecomendacao.getEmail() ),
                    "cadastro_recomendacao_email", "erro_carta_recomendacao_email_vazio" );
            }
        } );

        validador.onErrorForwardTo( getClass() ).solicitarRecomendacao();

        cartaDeRecomendacaoService.solicitarRecomendacao( cartaDeRecomendacao );

        result.include( "messages", "email_sent" );
        
//        this.solicitarRecomendacao();
        
        result.redirectTo( getClass() ).solicitarRecomendacao();
        
    }

    @Get
    @Path( "/cartaRecomendacao/reenviarRecomendacao/{cartaDeRecomendacao.cartaDeRecomendacaoID}" )
    @RestrictAccessPerfil( values = {
        TipoPerfil.COORDENADOR, TipoPerfil.PROFESSOR, TipoPerfil.SECRETARIA
    } )
    public void reenviarRecomendacao(
        final CartaDeRecomendacao cartaDeRecomendacao )
    {
        cartaDeRecomendacaoService.reenviarRecomendacao( cartaDeRecomendacao );
        
        result.include( "messages", "email_sent" );
        
        this.solicitarRecomendacao();
        //result.forwardTo( getClass() ).solicitarRecomendacao();
    }

    @Get
    @Path( "/cartaRecomendacao/dadosRecomendacao/{hashRecomendacao}" )
    @IrrestrictAccess
    public void dadosRecomendacao(
        final String hashRecomendacao )
    {
        CartaDeRecomendacao cartaDeRecomendacao;

        if( this.cartaDeRecomendacao == null )
            cartaDeRecomendacao = cartaDeRecomendacaoService.procurarPorHash( hashRecomendacao );
        else
            cartaDeRecomendacao = this.cartaDeRecomendacao;

        TipoProcessoSeletivo tipoProcessoSeletivo = null;
        if( cartaDeRecomendacao != null ) {
            final Inscricao inscricao = inscricaoService.getInscricaoAtual( cartaDeRecomendacao.getUsuario() );
            final ProcessoSeletivo processoSeletivo = inscricao.getProcessoSeletivo();

            if( processoSeletivo != null )
                tipoProcessoSeletivo = processoSeletivo.getTipoProcessoSeletivo();
        }
        result.include( "cartaDeRecomendacao", cartaDeRecomendacao );
        result.include( "tiposPais", TipoPais.getTiposPais() );
        result.include( "tiposConheceCandidato", TipoConheceCandidato.getTipoConheceCandidatos() );
        result.include( "tiposCategoriaCandidato",
            TipoCategoriaCandidato.getTipoCategoriaCandidatos() );
        result.include( "tipoProcessoSeletivo", tipoProcessoSeletivo );

    }

    @Post
    @Path( "/cartaRecomendacao/dadosRecomendacao" )
    @Transactional
    @IrrestrictAccess
    public void dadosRecomendacao(
        final CartaDeRecomendacao cartaDeRecomendacao )
    {

        validador.checking( new Validations() {
            {
                if( cartaDeRecomendacao != null ) {
                    that( StringUtils.hasText( cartaDeRecomendacao.getNome() ),
                        "cadastro_recomendacao_nome", "erro_campo_nulo" );

                    that( StringUtils.hasText( cartaDeRecomendacao.getInstituicao() ),
                        "cadastro_recomendacao_instituicao", "erro_campo_nulo" );

                    that( StringUtils.hasText( cartaDeRecomendacao.getCargoQueOcupa() ),
                        "cadastro_recomendacao_cargo_professor", "erro_campo_nulo" );

                    that( StringUtils.hasText( cartaDeRecomendacao.getGrauAcademicoMaisAlto() ),
                        "cadastro_recomendacao_grau_academico_adquirido", "erro_campo_nulo" );

                    that( StringUtils.hasText( cartaDeRecomendacao.getAreaProfessor() ),
                        "cadastro_recomendacao_grau_area", "erro_campo_nulo" );

                    that( StringUtils.hasText( cartaDeRecomendacao.getInstituicaoObteveGrau() ),
                        "cadastro_recomendacao_grau_instituicao", "erro_campo_nulo" );

                    that(
                        StringUtils.hasText( cartaDeRecomendacao.getEnderecoCorrespondencia().getTelefone().getCodTelefone() ),
                        "cadastro_dados_pessoais_telefone_contato", "erro_campo_nulo" );

                    that( StringUtils.hasText( cartaDeRecomendacao.getTempoConheceCandidato() ),
                        "cadastro_recomendacao_tempo_que_conhece_candidato", "erro_campo_nulo" );

                    if( cartaDeRecomendacao.getTipoConheceCandidato().equals(
                        TipoConheceCandidato.OUTROS ) ) {
                        that(
                            StringUtils.hasText( cartaDeRecomendacao.getOutraCondicaoConheceCandidato() ),
                            "erro_tipo_cadastro_recomendacao_outra_condicao_conhece_candidato",
                            "erro_favor_especificar" );
                    }

                    that( StringUtils.hasText( cartaDeRecomendacao.getAntecedentesAcademicos() ),
                        "erro_tipo_cadastro_recomendacao_antecedente_academico", "erro_campo_nulo" );

                    that( StringUtils.hasText( cartaDeRecomendacao.getAproveitamentoSeAceito() ),
                        "erro_tipo_cadastro_recomendacao_possivel_aproveitamento",
                        "erro_campo_nulo" );

                    if( ! cartaDeRecomendacao.getTipoCategoriaCandidato().equals(
                        TipoCategoriaCandidato.NAO_TENHO_COMO_FORNECER ) ) {
                        that(
                            StringUtils.hasText( cartaDeRecomendacao.getContextoCategoriaCantidato() ),
                            "erro_tipo_cadastro_recomendacao_contexto_categoria_candidato",
                            "erro_campo_nulo" );
                    }

                }
            }
        } );

        CartaDeRecomendacao carta = cartaDeRecomendacaoService.procurarPorHash( cartaDeRecomendacao.getHash() );

        this.cartaDeRecomendacao = cartaDeRecomendacao;
        this.cartaDeRecomendacao.setUsuario( carta.getUsuario() );
        this.cartaDeRecomendacao.setLingua( carta.getLingua() );

        validador.onErrorForwardTo( getClass() ).dadosRecomendacao( cartaDeRecomendacao.getHash() );
        this.cartaDeRecomendacao = null;

        // TODO: Executar servico para persistir carta de recomendacao

        cartaDeRecomendacaoService.copiaDados( cartaDeRecomendacao, carta );

        cartaDeRecomendacaoService.salvarOuAtualizar( carta );
        
        cartaDeRecomendacaoService.enviarCartaConfirmacaoRecebimento(cartaDeRecomendacao);

        result.include( "messages", "cadastro_recomendacao_mensagem_sucesso" );
        result.redirectTo( IndexController.class).index();
    }

}
